# pragma once

# include "serialib.h"
# include "socat_manager.h"

class serial_logger
{
private:
    char buffer[1024];
    int bytesRead;

    // 默认配置
    const unsigned int baudRate = 115200;
    const std::string physicalPort = "/dev/ttyUSB0";
    const std::string virtualTx = "/tmp/virtual_tx";
    const std::string virtualRx = "/tmp/virtual_rx";
    const std::string logFile = "serial_log_" + 
        std::to_string(std::time(nullptr)) + ".txt";

    serialib serialPhysical, serialVirtual;

    bool isRunning = false;
    std::ofstream logStream;
public:
    /// @brief 
    /// @param arg1 baudRate
    /// @param arg2 physicalPort
    /// @param arg3 virtualTx
    /// @param arg4 virtualRx
    /// @param arg5 logFile
    serial_logger(
        unsigned int arg1, 
        std::string arg2, 
        std::string arg3, 
        std::string arg4, 
        std::string arg5)
        : 
        baudRate(arg1),
        physicalPort(arg2),
        virtualTx(arg3),
        virtualRx(arg4),
        logFile(arg5)
    {
        startSocat(virtualTx, virtualRx);

        int physicalResult = serialPhysical.openDevice(
            physicalPort.c_str(), 
            baudRate, 
            SERIAL_DATABITS_8,
            SERIAL_PARITY_NONE,
            SERIAL_STOPBITS_1
        );

        if (physicalResult != 1) 
        {
            stopSocat(virtualTx, virtualRx);

            throw std::runtime_error("无法打开物理串口 " + physicalPort + ": " + getErrorString(physicalResult));
        }

        std::cout << "已连接物理串口: " << physicalPort << " 波特率: " << baudRate << std::endl;
        
        int virtualResult = serialVirtual.openDevice(
            virtualTx.c_str(), 
            baudRate, 
            SERIAL_DATABITS_8,
            SERIAL_PARITY_NONE,
            SERIAL_STOPBITS_1
        );
        
        if (virtualResult != 1) 
        {
            serialPhysical.closeDevice();
            stopSocat(virtualTx, virtualRx);
            throw std::runtime_error("无法打开虚拟串口 " + virtualTx + ": " + getErrorString(virtualResult));
        }
        std::cout << "连接虚拟串口以接收数据: " << virtualRx << std::endl;

        // 检查路径是否存在
        std::filesystem::path dirPath = std::filesystem::path(logFile).parent_path();
        if (!std::filesystem::exists(dirPath) && !dirPath.empty())
        {
            // 尝试创建路径
            try
            {
                if (!std::filesystem::create_directories(dirPath)) 
                {
                    std::cerr << "创建路径失败: " << dirPath << std::endl;
                }
            }
            catch(const std::exception& e)
            {
                std::cerr << "创建路径失败: " << dirPath << '\n' << e.what() << '\n';
            }
        }

        logStream = std::ofstream(logFile, std::ios::out | std::ios::trunc);
        if (!logStream.is_open()) {
            serialVirtual.closeDevice();
            serialPhysical.closeDevice();
            stopSocat(virtualTx, virtualRx);
            throw std::runtime_error("无法打开日志文件: " + logFile);
        }
        std::cout << "日志文件已打开: " << logFile << std::endl;
    };

    ~serial_logger()
    {
        stop();

        logStream.close();
        serialVirtual.closeDevice();
        serialPhysical.closeDevice();
        stopSocat(virtualTx, virtualRx);
    };

    void run()
    {
        isRunning = true;

        serialPhysical.readBytes(buffer, sizeof(buffer), 1);
        while (isRunning) 
        {
            // 从物理串口读取二进制数据
            bytesRead = serialPhysical.readBytes(buffer, sizeof(buffer), 1);
            if (bytesRead > 0) {
                // 1. 转发原始二进制数据到虚拟串口
                serialVirtual.writeBytes(buffer, bytesRead);
                
                // 2. 转为十六进制字符串记录到日志（关键修改）
                std::string hexData = binaryToHex(buffer, bytesRead);
                double timestamp = getCurrentTimeAsDouble();
                logStream << "[" << std::fixed << std::setprecision(8) << timestamp << "]: " << hexData << std::endl;
                
                // 3. 控制台输出十六进制（方便查看）
                std::cout << "[" << timestamp << "]: " << hexData << std::endl;
            }
        }
    }

    void stop()
    {
        isRunning = false;
    }
};
